/*
 * Copyright (c) 2020 - present, Inspur Genersoft Co., Ltd.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License. 
 */

package io.iec.edp.caf.multicontext.support;

import io.iec.edp.caf.commons.runtime.CafEnvironment;
import io.iec.edp.caf.multicontext.config.ParallelSetting;
import io.iec.edp.caf.multicontext.config.SpecialModule;

import java.io.File;
import java.io.FileFilter;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 模块拆分计算器
 * @author wangyandong
 */
public class ModuleSplittingCalculator {
    /**
     * 根据并行设置计算拆分的模块
     * @param setting
     * @return
     */
    public static List<SpecialModule> calculate(ParallelSetting setting){
        List<SpecialModule> modules = new ArrayList<>();
        String basePath = CafEnvironment.getServerRTPath() + "/";

        //合并模块排除列表
        List<String> excludePaths = setting.getExcludes().stream()
                .map(url -> basePath + url).collect(Collectors.toList());

        excludePaths.addAll(setting.getBasePaths().stream().map(url -> basePath + url).collect(Collectors.toList()));

        if(setting.getSpecialModules()!=null) {
            setting.getSpecialModules().forEach(sm -> {
                sm.getIncludes().forEach(url -> {
                    excludePaths.add(basePath + url);
                });
            });
        }

        //扫描include列表，查找关键应用路径
        int count=0;
        for (int i = 0; i < setting.getIncludes().size(); i++) {
            String url = setting.getIncludes().get(i);
            File file = new File(basePath + url);
            if(!file.exists() || file.isFile())
                continue;
            String parentName = file.getName();
            //每个目录均为关键应用
            File[] files = file.listFiles(new DirFilter(excludePaths));
            //to do 过滤子级目录、platform是否按su启动
            //每个关键应用作为一个模块
            modules.addAll(buildModules(parentName, files,true));
        }
        //特殊模块
        if(setting.getSpecialModules()!=null){
            setting.getSpecialModules().forEach(module->{
                SpecialModule sm = new SpecialModule();
                sm.setName(module.getName());
                List<String> finalIncludes = new ArrayList<>();
                Map<String,String> sus = new HashMap<>();
                //将特殊模块的su及url信息记录下来
                for(String includePath:module.getIncludes()){
                    finalIncludes.add(basePath + includePath);
                    File suFile = new File(basePath+includePath);
                    ServiceUnitManager.getServiceUnitInfo(sus,suFile);
                }
                sm.setIncludes(finalIncludes);
                sm.setSuMapping(sus);
//                sm.setIncludes(module.getIncludes().stream()
//                        .map(url -> basePath + url).collect(Collectors.toList()));
                modules.add(sm);
            });
        }
        return modules;
    }

    private static List<SpecialModule> buildModules(String parentName, File[] files, boolean mergeIntoOne){
        List<SpecialModule> modules = new ArrayList<>();
        if(mergeIntoOne) {
            for (int j = 0; j < files.length; j++) {
                List<String> includes = new ArrayList<>();
                includes.add(files[j].getAbsolutePath());
                String moduleName = files[j].getName();
                String name = String.format("module-%s-%s", parentName, moduleName);
                //su name,path
                Map<String,String> sus = new HashMap<>();
                ServiceUnitManager.getServiceUnitInfo(sus,files[j]);

                SpecialModule module = new SpecialModule(name,includes,sus);
                modules.add(module);
            }
        }else{
            SpecialModule module = new SpecialModule();
            module.setName(String.format("module-%s", parentName));
            module.setIncludes(new ArrayList<>());
            for (int j = 0; j < files.length; j++) {
                String url = files[j].getAbsolutePath();
                module.getIncludes().add(url);
            }
            modules.add(module);
        }
        return modules;
    }

}

/**
 * 做一层简单过滤，排除在exclude列表中的路径
 */
class DirFilter implements FileFilter {
    private List<String> excludePaths;
    public DirFilter(List<String> excludePaths){
        this.excludePaths = excludePaths;
    }
    //重写accept()抽象方法
    public boolean accept(File file) {
        if(file.isFile())
            return false;
        return !this.excludePaths.contains(file.getAbsolutePath().replaceAll("\\\\","/"));
    }
}
